package com.weixing.mall.provider.util;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.NumberUtil;
import com.google.common.collect.Lists;
import com.weixing.mall.base.constant.GlobalConstant;
import com.weixing.mall.base.utils.EnumUtil;
import com.weixing.mall.provider.api.model.CalcProfitPo;
import com.weixing.mall.provider.api.model.enums.AgentLevelEnum;
import com.weixing.mall.provider.api.model.enums.AgentRebateRuleEnum;
import com.weixing.mall.provider.api.model.enums.AgentTypeEnum;
import com.weixing.mall.provider.model.domain.*;
import com.weixing.mall.provider.model.enums.AgentPayChannelEnum;
import com.weixing.mall.provider.model.enums.AgentPayTypeEnum;
import com.weixing.mall.provider.model.enums.InfoPerfectEnum;
import com.weixing.mall.provider.model.vo.AgencyFeeVo;
import com.weixing.mall.provider.model.vo.AgentBonusVo;
import com.weixing.mall.provider.model.vo.AgentRenewVo;
import com.weixing.mall.provider.model.vo.RuleInfoVo;
import com.weixing.mall.provider.model.vo.renew.AgencyRecordExcelData;
import com.weixing.mall.provider.model.vo.renew.AgentRenewEditVo;
import com.weixing.mall.provider.support.excel.AgencyExcelDownData;
import com.weixing.mall.provider.support.excel.BonusExcelDownData;
import org.springframework.util.Assert;

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.List;

/**
 * @Author: kfc
 * @Description: <br/>
 * Date:Create in 2019/9/10 15:44
 * @Modified By:
 */
public class AgentUtil {

    /**
     * 生成代理商编号
     *
     * @param num
     * @return
     */
    public static String createAgentSn(int num) {
        return String.format("%08d", num);
    }


    /**
     * 方法描述:此方法供AgentRebateRuleEnum调用
     * @Author Small
     * @param agentArr
     * @param list
     * @Date 2019/10/22 15:08
     * @return void
     */
    public static void fmtForEnum(String[] agentArr, List<List<String>> list) {
        int size = list.size();
        // 格式化组合
        for (int i = 0; i < size; i++) {
            List<String> ls = list.get(i);
            String rs = "";
            String rsb = "";
            for (int j = 0; j < agentArr.length; j++) {
                String s1 = agentArr[j];
                if (ls.contains(s1)) {
                    rs += s1 + "|";
                    rsb += 1;
                } else {
                    rs += "0|";
                    rsb += 0;
                }
            }
            // 处理rs,不足6位，补0
            int length = rs.split("\\|").length;
            if (length < 6) {
                for (int j = 0; j < 6 - length; j++) {
                    rs += "0|";
                }
            }
            rs = rs.substring(0, rs.lastIndexOf("|"));
            // 处理rsb,不足6位，补0
            int length1 = rsb.length();
            if (length1 < 6) {
                for (int j = 0; j < 6 - length1; j++) {
                    rsb += "0";
                }
            }
            Integer index = Integer.valueOf(rsb, 2);
            System.out.println("RULE" + index + "(" + index + ",\"" + rs + "\"),");
        }

    }


    public static ArrayList<RuleInfoVo> fmtForPage(String[] agentArr, List<List<String>> list) {
        int size = list.size();
        ArrayList<RuleInfoVo> result = new ArrayList<>();
        RuleInfoVo dto = null;
        // 格式化组合
        for (int i = 0; i < size; i++) {
            List<String> ls = list.get(i);
            String rs = "";
            String rsb = "";
            for (int j = 0; j < agentArr.length; j++) {
                String s1 = agentArr[j];
                if (ls.contains(s1)) {
                    rs += s1 + "|";
                    rsb += 1;
                } else {
                    rs += "0|";
                    rsb += 0;
                }
            }
            // 处理rs,不足6位，补0
            int length = rs.split("\\|").length;
            if (length < 6) {
                for (int j = 0; j < 6 - length; j++) {
                    rs += "0|";
                }
            }
            rs = rs.substring(0, rs.lastIndexOf("|"));
            // 处理rsb,不足6位，补0
            int length1 = rsb.length();
            if (length1 < 6) {
                for (int j = 0; j < 6 - length1; j++) {
                    rsb += "0";
                }
            }
            Integer code = Integer.valueOf(rsb, 2);
            dto = new RuleInfoVo();
            dto.setInfoCode(code);
            dto.setRuleInfo(rs);
            dto.setRemark("");
            // 分佣比例设置
            for (int k = 0; k < 6; k++) {
                char c = rsb.charAt(k);
                String s = String.valueOf(c);
                dto.setLevelEnable(k + 1, Integer.valueOf(s).intValue());
            }
            result.add(dto);
        }
        return result;
    }

    /**
     * 方法描述:  从m个元素的集合中取n个数排列组合
     * @Author Small
     * @param agentArr  数组集合(集合length即为m)
     * @param n  取n个值排列
     * @Date 2019/10/22 15:06
     * @return java.util.List
     */
    public static List mn(String[] agentArr, int n) {
        // 存放单个组合的容器
        ArrayList temp = new ArrayList();
        // 最终组合
        ArrayList<List<String>> finalList = new ArrayList<>();
        for (int i = 1; i <= n; i++) {
            // 选n时的组合
            ArrayList<List<String>> result = new ArrayList();
            List<List<String>> comb = comb(agentArr, temp, result, 0, i);
            finalList.addAll(comb);
        }
        return finalList;
    }

    /**
     * 方法描述: m取n时排列组合
     * @Author Small
     * @param arry     代理商数组
     * @param temp     临时数组
     * @param result   最终数组
     * @param s        数组坐标（从0开始）
     * @param n        从数组中取出n个元素
     * @Date 2019/10/22 15:03
     * @return java.util.List<java.util.List < java.lang.String>>
     */
    private static List<List<String>> comb(String[] arry, ArrayList temp, ArrayList result, int s, int n) {

        int m = arry.length;
        Assert.isTrue(n <= m, "n必须比数组长度小");
        for (int i = s; i < m; i++) {
            ArrayList l2 = new ArrayList();
            l2.addAll(temp);
            l2.add(arry[i]);
            if (l2.size() >= n) {
                result.add(l2);
                continue;
            } else {
                comb(arry, l2, result, i + 1, n);
            }
        }
        return result;
    }

    /**
     * 方法描述: 根据上级代理的返利规则编号和自己当前的代理级别所返利规则编号计算出绑定关系后的新返利规则编号
     * @Author Small
     * @param parentRebateRule    上级代理返利规则编号
     * @param ownAgentLevel       自己的代理级别
     * @Date 2019/12/16 19:41
     * @return com.weixing.mall.provider.api.model.enums.AgentRebateRuleEnum
     */
    public static AgentRebateRuleEnum calcAgentRebateRule(int parentRebateRule, int ownAgentLevel) {
        int finalRule = parentRebateRule + getRebateRuleByAgentLevel(ownAgentLevel).getValue();
        AgentRebateRuleEnum iEnum = EnumUtil.getIEnum(AgentRebateRuleEnum.class, String.valueOf(finalRule));
        return iEnum;
    }

    /**
     * 方法描述: 根据代理商ids判断该结构树所对应的返利规则
     * @Author Small
     * @param agentLevelArr
     * @Date 2020/2/24 16:14
     * @return int
     */
    public static int calcRebateRule(int[] agentLevelArr) {
        int sum = 0;
        for (int i : agentLevelArr) {
            AgentLevelEnum iEnum = EnumUtil.getIEnum(AgentLevelEnum.class, i);
            sum = add(sum, iEnum.getCode());

        }
        return sum;
    }

    /**
     * 方法描述: 根据int值解析出代理商等级对应的返利规则枚举
     * @Author Small
     * @param agentLevel
     * @Date 2019/12/17 18:47
     * @return com.weixing.mall.provider.api.model.enums.AgentRebateRuleEnum
     */
    public static AgentRebateRuleEnum getRebateRuleByAgentLevel(int agentLevel) {
        AgentLevelEnum agentLevelEnum = parseLevel(agentLevel);
        return agentLevelEnum.getRebateRule();
    }

    /**
     * 方法描述: 根据int值解析出代理商等级对应的枚举
     * @Author Small
     * @param agentLevel
     * @Date 2019/12/17 18:46
     * @return com.weixing.mall.provider.api.model.enums.AgentLevelEnum
     */
    public static AgentLevelEnum parseLevel(int agentLevel) {
        return EnumUtil.getIEnum(AgentLevelEnum.class, String.valueOf(agentLevel));
    }


    /**
     * 方法描述:计算代理商树结构
     * @Author Small
     * @param parentTreePath     父代理树结构
     * @param agent     代理商
     * @Date 2020/2/20 15:16
     * @return java.lang.String
     */
    public static String calcAgentTreePath(String parentTreePath, Agent agent) {
        StringBuilder sb = new StringBuilder();
        sb.append(calcAgentTreePath(agent))
                .append(GlobalConstant.symbol.SINGLE_VERTICAL_LINE)
                .append(parentTreePath);
        return sb.toString();
    }


    /**
     * 方法描述:计算代理商树结构
     * @Author Small
     * @param agent     代理
     * @Date 2020/2/20 15:16
     * @return java.lang.String
     */
    public static String calcAgentTreePath(Agent agent) {
        StringBuilder sb = new StringBuilder();
        sb
                .append(agent.getAgentLevel().intValue())
                .append(GlobalConstant.symbol.MH)
                .append(agent.getAgentType().intValue())
                .append(GlobalConstant.symbol.MH)
                .append(agent.getId())
                .append(GlobalConstant.symbol.MH)
                .append(agent.getDiscount().doubleValue());
        return sb.toString();
    }

    /**
     * 方法描述:根据代理商等级和类型获取所对应的折扣值
     * @Author Small
     * @param actAgentDiscount
     * @param level
     * @param type
     * @Date 2020/2/24 17:37
     * @return java.math.BigDecimal
     */
    public static BigDecimal calcDisCount(AgentDiscount actAgentDiscount, int level, int type) {
        AgentLevelEnum agentLevel = EnumUtil.getIEnum(AgentLevelEnum.class, level);

        BigDecimal disCount = null;
        switch (agentLevel) {
            case DEALER:
                if (AgentTypeEnum.GOLD.getValue().intValue() == type) {
                    disCount = actAgentDiscount.getDistributorGold();
                } else {
                    disCount = actAgentDiscount.getDistributorSilver();
                }
                break;
            case LEVEL_1:
                if (AgentTypeEnum.GOLD.getValue().intValue() == type) {
                    disCount = actAgentDiscount.getFirstLevelGold();
                } else {
                    disCount = actAgentDiscount.getFirstLevelSilver();
                }
                break;
            case LEVEL_2:
                if (AgentTypeEnum.GOLD.getValue().intValue() == type) {
                    disCount = actAgentDiscount.getSecondLevelGold();
                } else {
                    disCount = actAgentDiscount.getSecondLevelSilver();
                }
                break;
            case LEVEL_3:
                if (AgentTypeEnum.GOLD.getValue().intValue() == type) {
                    disCount = actAgentDiscount.getThirdLevelGold();
                } else {
                    disCount = actAgentDiscount.getThirdLevelSilver();
                }
                break;
        }
        return disCount;
    }

    /**
     * 方法描述:根据代理商等级和类型获取所对应的折扣值
     * @Author Small
     * @param rebateRuleInfo
     * @param level
     * @param type
     * @Date 2020/2/24 17:37
     * @return java.math.BigDecimal
     */
    public static BigDecimal calcDisCount(AgentRebateRuleInfo rebateRuleInfo, int level, int type) {
        AgentLevelEnum agentLevel = EnumUtil.getIEnum(AgentLevelEnum.class, level);

        BigDecimal disCount = null;
        switch (agentLevel) {
            case DEALER:
                disCount = rebateRuleInfo.getAgentLevel1();
                break;
            case LEVEL_1:
                disCount = rebateRuleInfo.getAgentLevel2();
                break;
            case LEVEL_2:
                disCount = rebateRuleInfo.getAgentLevel3();
                break;
            case LEVEL_3:
                disCount = rebateRuleInfo.getAgentLevel4();
                break;
            case LEVEL_4:
                disCount = rebateRuleInfo.getAgentLevel5();
                break;
            case LEVEL_5:
                disCount = rebateRuleInfo.getAgentLevel6();
                break;
        }
        return disCount;
    }

    public static int add(int flag, int level) {
        return flag | level;
    }


    /**
     * 封装代理商缴费列表Excel下载对象
     *
     * @param voList  元数据列表
     * @return List<AgencyExcelDownData>
     */
    public static List<AgencyExcelDownData> wapperAgencyExcelData(List<AgencyFeeVo> voList) {
        List<AgencyExcelDownData> dataList = Lists.newArrayList();
        AgencyExcelDownData data = null;
        if (CollUtil.isNotEmpty(voList)) {
            for (AgencyFeeVo vo : voList) {
                data = new AgencyExcelDownData();
                data.setAgentSn(vo.getAgentSn());
                data.setAgentName(vo.getAgentName());
                data.setAgencyFeeMonth(vo.getAgencyFeeMonth());
                data.setAgencyFeeYear(vo.getAgencyFeeYear());
                data.setAgentLevel(vo.getAgentLevel().getDesp());
                data.setCustomerName(vo.getCustomerName());
                data.setFirstRenewTime(vo.getFirstRenewTime());
                data.setMobile(vo.getMobile());
                dataList.add(data);
            }
        }
        return dataList;
    }

    /**
     * 封装代理商缴费列表Excel下载对象
     *
     * @param voList 元数据列表
     * @return 下载列表
     */
    public static List<AgencyRecordExcelData> wapperAgencyRecordExcelData(List<AgentRenewVo> voList) {
        List<AgencyRecordExcelData> dataList = Lists.newArrayList();
        AgencyRecordExcelData data = null;
        if (CollUtil.isNotEmpty(voList)) {
            for (AgentRenewVo vo : voList) {
                data = new AgencyRecordExcelData();
                data.setAgentSn(vo.getAgentSn());
                data.setAgentName(vo.getAgentName());
                data.setCustomerName(vo.getCustomerName());
                data.setLoginMobile(vo.getMobile());
                data.setWechatNum(vo.getWechatNum());
                data.setMobile(vo.getMobile());
                data.setIdCard(vo.getIdCard());
                data.setIsExpire(vo.getIsExpire() == 0 ? "否" : "是");
                data.setIsOfficial(vo.getIsOfficial() == 0 ? "否" : "是");
                data.setIsBlack(vo.getIsBlack() == 0 ? "否" : "是");
                data.setIsEnable(vo.getIsEnable() == 0 ? "否" : "是");
                data.setPayChannel(vo.getPayChannel().getDesp());
                data.setAmount(vo.getAmount());
                data.setCreator(vo.getCreator());
                data.setAgentLevel(EnumUtil.getDesp(AgentLevelEnum.class,vo.getAgentLevel()));
                data.setCreatedTime(vo.getCreatedTime());
                data.setEffectStart(vo.getEffectStart());
                data.setEffectEnd(vo.getEffectEnd());
                dataList.add(data);
            }
        }
        return dataList;
    }


    /**
     * 方法描述: 封装代理商分红列表Excel下载对象
     * @Author Small
     * @param voList
     * @Date 2020/3/8 14:20
     * @return java.util.List<com.weixing.mall.provider.support.excel.AgencyExcelDownData>
     */
    public static List<BonusExcelDownData> wapperBonusExcelData(List<AgentBonusVo> voList) {
        List<BonusExcelDownData> dataList = Lists.newArrayList();
        BonusExcelDownData data = null;
        if (CollUtil.isNotEmpty(voList)) {
            for (AgentBonusVo vo : voList) {
                data = new BonusExcelDownData();
                data.setAgentSn(vo.getAgentSn());
                data.setAgentName(vo.getAgentName());
                data.setMobile(vo.getMobile());
                data.setOrderType(vo.getOrderType().getDesp());
                data.setOrderSn(vo.getOrderSn());
                data.setOrderPrice(vo.getOrderPrice());
                data.setOrderGmtTime(vo.getOrderGmtTime());
                data.setBonusTeamName(vo.getBonusTeamName());
                data.setBonusAmount(vo.getBonusAmount());
                data.setKefu(vo.getKefu());
                dataList.add(data);
            }
        }
        return dataList;
    }

    public static BigDecimal calcSumDiscount(AgentRebateRuleInfo agentRebateRuleInfo) {
        BigDecimal[] disArr = new BigDecimal[6];
        disArr[0] = agentRebateRuleInfo.getAgentLevel1();
        disArr[1] = agentRebateRuleInfo.getAgentLevel2();
        disArr[2] = agentRebateRuleInfo.getAgentLevel3();
        disArr[3] = agentRebateRuleInfo.getAgentLevel4();
        disArr[4] = agentRebateRuleInfo.getAgentLevel5();
        disArr[5] = agentRebateRuleInfo.getAgentLevel6();
        return NumberUtil.add(disArr);
    }

    public static List<CalcProfitPo> parseTreePath(String treePath) {
        String[] agentCliamDetail = treePath.split("\\|");
        List<CalcProfitPo> calcProfitPos = Lists.newArrayList();
        CalcProfitPo calcProfitPo = null;
        for (String agentDetail : agentCliamDetail) {
            String[] detail = agentDetail.split(":");
            int agentLevel = Integer.parseInt(detail[0]);
            int agentType = Integer.parseInt(detail[1]);
            BigDecimal discount = new BigDecimal(detail[3]);
            long agentId = Long.parseLong(detail[2]);
            calcProfitPo = new CalcProfitPo();
            calcProfitPo.setAgentId(agentId);
            calcProfitPo.setAgentLevel(agentLevel);
            calcProfitPo.setAgentType(agentType);
            calcProfitPo.setDiscount(discount);
            calcProfitPos.add(calcProfitPo);
        }
        return calcProfitPos;
    }

    /**
     * 方法描述: 更新代理结构树
     * @Author Small
     * @param agent
     * @Date 2020/3/17 9:58
     * @return void
     */
    public static void updateAgentTree(Agent agent) {
        String agentTreePath = agent.getAgentTreePath();
        List<CalcProfitPo> calcProfitPos = parseTreePath(agentTreePath);
        // 初始化原有等级
        agent.setDealerId(0L);
        agent.setLevel1st(0L);
        agent.setLevel2nd(0L);
        agent.setLevel3rd(0L);
        agent.setLevel4th(0L);
        for (CalcProfitPo po : calcProfitPos) {
            long agentId = po.getAgentId();
            AgentLevelEnum level = EnumUtil.getIEnum(AgentLevelEnum.class, po.getAgentLevel());
            switch (level) {
                case DEALER:
                    agent.setDealerId(agentId);
                    break;
                case LEVEL_1:
                    agent.setLevel1st(agentId);
                    break;
                case LEVEL_2:
                    agent.setLevel2nd(agentId);
                    break;
                case LEVEL_3:
                    agent.setLevel3rd(agentId);
                    break;
                case LEVEL_4:
                    agent.setLevel4th(agentId);
                    break;
            }
        }
    }

    public static void main(String[] args) {
//        String[] agentArry = new String[]{"经销商", "一级代理", "二级代理", "三级代理", "四级代理", "五级代理"};
//        List mn = mn(agentArry, 6);
//        fmtForEnum(agentArry,mn);


//        AgentRebateRuleEnum agentRebateRuleEnum = calcAgentRebateRule(31, 63);
//        System.out.println(agentRebateRuleEnum);

//
//        int[] arr = new int[]{3, 2};
//        int i = calcRebateRule(arr);
//        System.out.println(i);


//        AgentLevelEnum iEnum = EnumUtil.getIEnum(AgentLevelEnum.class, 7);
//        System.out.println(iEnum.getDesp());

//        String desp = EnumUtil.getDesp(AgentLevelEnum.class, 7);
//        System.out.println(desp);

        int i = 1;
    }


    public static AgentRenewEditVo wrapAgentRenewEditVo(AgentRenew agentRenew, Agent agent) {
        AgentRenewEditVo vo = new AgentRenewEditVo();
        vo.setId(agentRenew.getId());
        vo.setAgentId(agent.getId());
        vo.setAgentSn(agent.getAgentSn());
        vo.setAgentName(agent.getAgentName());
        vo.setAgentLevel(EnumUtil.getIEnum(AgentLevelEnum.class, agent.getAgentLevel()));
        vo.setAmount(agentRenew.getAmount());
        vo.setMaturityTime(agent.getMaturityTime());
        vo.setCreatedTime(agentRenew.getCreatedTime());
        vo.setCustomerName(agent.getCustomerName());
        vo.setEffectEnd(agentRenew.getEffectEnd());
        vo.setEffectStart(agentRenew.getEffectStart());
        vo.setMobile(agent.getMobile());
        vo.setPayChannel(EnumUtil.getIEnum(AgentPayChannelEnum.class, agentRenew.getPayChannel()));
        vo.setPayType(EnumUtil.getIEnum(AgentPayTypeEnum.class, agentRenew.getPayType()));
        vo.setAgencyFeeMonth(agent.getAgencyFeeMonth());
        vo.setAgencyFeeYear(agent.getAgencyFeeYear());
        return vo;
    }
}
